package com.yeyks.commonReference.service.vip.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.yeyks.account.dal.domain.AccountInfo;
import com.yeyks.common.base.Arguments;
import com.yeyks.common.base.PageResult;
import com.yeyks.common.constants.AccountType;
import com.yeyks.common.dto.AccountPayAccountDTO;
import com.yeyks.common.exception.ServiceException;
import com.yeyks.common.utils.FormatUtils;
import com.yeyks.common.utils.Splitters;
import com.yeyks.commonReference.pojo.param.minivipcard.MiniCardWithdrawalParam;
import com.yeyks.commonReference.service.account.AccountInfoService;
import com.yeyks.commonReference.service.vip.MiniCardCommissionOverviewService;
import com.yeyks.commonReference.service.vip.MiniCardWithdrawalOrderService;
import com.yeyks.vip.dal.domain.MiniCardWithdrawalOrder;
import com.yeyks.vip.dal.dao.MiniCardWithdrawalOrderMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yeyks.vip.param.MiniCardWithdrawalOrderListParam;
import com.yeyks.vip.param.MiniCardWithdrawalOrderUpdateParam;
import com.yeyks.vip.result.MiniCardWithdrawalOrderDownloadResult;
import com.yeyks.vip.result.MiniCardWithdrawalOrderListResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;


/**
 * <p>
 * 酒店小vip售卡佣金提现订单表 服务实现类
 * </p>
 *
 * @author yun
 * @since 2020-01-06
 */
@Service
@Slf4j
public class MiniCardWithdrawalOrderServiceImpl extends ServiceImpl<MiniCardWithdrawalOrderMapper, MiniCardWithdrawalOrder> implements MiniCardWithdrawalOrderService {
    @Autowired
    private AccountInfoService accountInfoService;
    @Autowired
    private MiniCardCommissionOverviewService overviewService;

    /**
     * 校验该用户是否可以提现
     *
     * @param param
     */
    public Boolean checkWithDraw(MiniCardWithdrawalParam param) {
        Arguments.intIsNull(param.getAccountId(), "账户id不能为空");
        Arguments.intIsNull(param.getAccountType(), "账户类型不能为空");
        //1.查询该账户信息
        AccountInfo accountInfo = accountInfoService.getById(param.getAccountId());
        Arguments.beanIsNull(accountInfo, "该账户不存在");
        //2.检验银行账户
        try {
            String bankData = accountInfo.getExtraInfo();
            Arguments.isFalse(bankData.contains("pay_accounts"), "您还未绑卡请先去绑卡");
            AccountPayAccountDTO payAccountDTO = JSONUtil.toBean(accountInfo.getExtraInfo(), AccountPayAccountDTO.class);
            if (null == payAccountDTO.getPayAccounts().getUserName()
                    || null == payAccountDTO.getPayAccounts().getBankCard()
                    || null == payAccountDTO.getPayAccounts().getBankName()) {
                throw new ServiceException("银行账号有误");
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info("提现账户银行卡信息有误AccountInfo = {}", accountInfo);
        }
        //3.校验提现订单
        List<MiniCardWithdrawalOrder> orders = baseMapper.selectList(new QueryWrapper<MiniCardWithdrawalOrder>()
                .eq(MiniCardWithdrawalOrder.ACCOUNT_ID, param.getAccountId())
                .eq(MiniCardWithdrawalOrder.ACCOUNT_TYPE, param.getAccountType())
                .eq(MiniCardWithdrawalOrder.STATUS, 1)
                .eq(MiniCardWithdrawalOrder.DELETE_FLAG, 0));
        Arguments.listNotNull(orders, "您有正在处理的提现订单");
        //查询n天已经提现成功的订单
        List<MiniCardWithdrawalOrder> miniCardWithdrawalOrders = baseMapper.selectNDayOrder(param.getAccountId(), param.getAccountType(), 2, param.getDays());
        if (CollectionUtil.isNotEmpty(miniCardWithdrawalOrders)) {
            if (miniCardWithdrawalOrders.size() >= param.getCount()) {
                throw new ServiceException(param.getDays() + "只能提现" + param.getCount() + "次");
            }
        }
        return true;
    }

    /**
     * 提现订单列表
     *
     * @param param {@link MiniCardWithdrawalOrderListParam}
     * @return
     */
    @Override
    public PageResult<MiniCardWithdrawalOrderListResult> myList(AccountInfo loginUser, MiniCardWithdrawalOrderListParam param) {
        QueryWrapper<MiniCardWithdrawalOrder> wrapper = getQueryWrapper(loginUser, param);
        PageHelper.startPage(param.getPageNum(), param.getPageSize());
        List<MiniCardWithdrawalOrder> orders = baseMapper.selectList(wrapper);
        PageInfo<MiniCardWithdrawalOrder> pageInfo = PageInfo.of(orders);
        List<MiniCardWithdrawalOrderListResult> results = Lists.newArrayList();
        for (MiniCardWithdrawalOrder order : orders) {
            MiniCardWithdrawalOrderListResult result = BeanUtil.toBean(order, MiniCardWithdrawalOrderListResult.class);
            result.setLastTime(getLastTime(order));
            results.add(result);
            //根据账户id账户类型和提现成功的状态查询上次提现成功的订单
        }
        return new PageResult<>(pageInfo.getTotal(),
                pageInfo.getPages(),
                pageInfo.isHasNextPage(),
                pageInfo.getNextPage(),
                results);
    }

    /**
     * 获取上次提现成功的时间
     *
     * @param order
     * @return
     */
    private Date getLastTime(MiniCardWithdrawalOrder order) {
        MiniCardWithdrawalOrder miniCardWithdrawalOrder = baseMapper.selectOne(new QueryWrapper<MiniCardWithdrawalOrder>()
                .eq(MiniCardWithdrawalOrder.STATUS, MiniCardWithdrawalOrder.Status.success.value())
                .eq(MiniCardWithdrawalOrder.ACCOUNT_ID, order.getAccountId())
                .eq(MiniCardWithdrawalOrder.ACCOUNT_TYPE, order.getAccountType())
                .lt(MiniCardWithdrawalOrder.CREATE_TIME, order.getCreateTime())
                .orderByDesc(MiniCardWithdrawalOrder.CREATE_TIME)
                .last("limit 1"));
        if (null == miniCardWithdrawalOrder) {
            return null;
        }
        return miniCardWithdrawalOrder.getCreateTime();
    }

    /**
     * 生成提现订单列表搜索条件
     *
     * @param param
     * @return
     */
    private QueryWrapper<MiniCardWithdrawalOrder> getQueryWrapper(AccountInfo loginUser, MiniCardWithdrawalOrderListParam param) {
        QueryWrapper<MiniCardWithdrawalOrder> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc(MiniCardWithdrawalOrder.CREATE_TIME);
        if (AccountType.Administrator != loginUser.getType()) {
            wrapper.eq(MiniCardWithdrawalOrder.ACCOUNT_ID, loginUser.getId());
            wrapper.eq(MiniCardWithdrawalOrder.ACCOUNT_TYPE, loginUser.getType());
        }
        if (StrUtil.isNotBlank(param.getAccountName())) {
            wrapper.like(MiniCardWithdrawalOrder.ACCOUNT_NAME, param.getAccountName());
        }
        if (StrUtil.isNotBlank(param.getAccountPhone())) {
            wrapper.like(MiniCardWithdrawalOrder.ACCOUNT_PHONE, param.getAccountPhone());
        }
        if (ObjectUtil.isNotNull(param.getStatus())) {
            wrapper.like(MiniCardWithdrawalOrder.STATUS, param.getStatus());
        }
        if (ObjectUtil.isNotNull(param.getStartTime()) && ObjectUtil.isNotNull(param.getEndTime())) {
            wrapper.between(MiniCardWithdrawalOrder.CREATE_TIME, new Date(param.getStartTime()), new Date(param.getEndTime()));
        }
        return wrapper;
    }

    /**
     * 修改提现订单状态
     *
     * @param loginUser 当前登录账户
     * @param param     {@link MiniCardWithdrawalOrderUpdateParam}
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean pass(AccountInfo loginUser, MiniCardWithdrawalOrderUpdateParam param) {
        //检验账户类型权限
        Arguments.isFalse(AccountType.Administrator == loginUser.getType(), "您无权访问");
        //查询订单
        MiniCardWithdrawalOrder order = selectByOrderNo(param.getOrderNo());
        Arguments.beanIsNull(order, "该提现订单不存在");
        Arguments.isTrue(param.getStatus().equals(order.getStatus()), "相同状态不能修改");
        Arguments.isFalse(order.getStatus().equals(MiniCardWithdrawalOrder.Status.wait.value()), "非审核中状态不能修改");
        //拒绝的话佣金回退
        if (MiniCardWithdrawalOrder.Status.reject.value().equals(param.getStatus())) {
            overviewService.reject(param.getOrderNo());
        }
        //订单状态修改
        order.setStatus(param.getStatus());
        if (StrUtil.isNotBlank(param.getRemark())) {
            order.setRemark(param.getRemark());
        } else {
            if (MiniCardWithdrawalOrder.Status.success.value().equals(param.getStatus())) {
                order.setRemark(MiniCardWithdrawalOrder.Status.success.desc());
            }
            if (MiniCardWithdrawalOrder.Status.reject.value().equals(param.getStatus())) {
                order.setRemark(MiniCardWithdrawalOrder.Status.reject.desc());
            }
        }
        order.setOperatorId(loginUser.getId());
        order.setUpdateTime(new Date());
        Arguments.isFalse(1 == baseMapper.updateById(order), "订单状态修改失败");
        return true;
    }

    /**
     * 批量修改提现订单状态为审核通过
     *
     * @param loginUser 当前登录账户
     * @param orderNo   订单号集合逗号隔开
     * @return
     */
    @Override
    public Boolean myUpdateMore(AccountInfo loginUser, String orderNo) {
        Arguments.isFalse(AccountType.Administrator == loginUser.getType(), "您无权访问");
        List<String> orderNos = Splitters.splitToString(orderNo, Splitters.COMMA);
        Date date = new Date();
        for (String no : orderNos) {
            MiniCardWithdrawalOrder order = baseMapper.selectOne(new QueryWrapper<MiniCardWithdrawalOrder>()
                    .eq(MiniCardWithdrawalOrder.ORDER_NO, no).last("limit 1"));
            if (!MiniCardWithdrawalOrder.Status.wait.value().equals(order.getStatus())) {
                log.info("该订单非申请结算中状态{}", order.getOrderNo());
                throw new ServiceException("该订单非申请结算中状态");
            }
            order.setOperatorId(loginUser.getId());
            order.setStatus(MiniCardWithdrawalOrder.Status.success.value());
            order.setUpdateTime(date);
            Arguments.isFalse(baseMapper.updateById(order) == 1, "更新订单状态失败");
        }
        return true;
    }

    /**
     * 提现订单导出
     *
     * @param param
     * @return
     */
    @Override
    public List<MiniCardWithdrawalOrderDownloadResult> orderDownload(AccountInfo loginUser, MiniCardWithdrawalOrderListParam param) {
        List<MiniCardWithdrawalOrder> orders = baseMapper.selectList(getQueryWrapper(loginUser, param));
        List<MiniCardWithdrawalOrderDownloadResult> results = Lists.newArrayList();
        orders.forEach(e -> {
            MiniCardWithdrawalOrderDownloadResult result = BeanUtil.toBean(e, MiniCardWithdrawalOrderDownloadResult.class);
            result.setStatus(MiniCardWithdrawalOrder.Status.getDesc(e.getStatus()));
            result.setCreateTime(DateUtil.format(e.getCreateTime(), DatePattern.NORM_DATETIME_PATTERN));
            result.setAmount(FormatUtils.fenToYuan(e.getAmount()));
            results.add(result);
        });
        return results;
    }

    /**
     * 通过订单号查询该提现订单
     *
     * @param orderNo
     * @return
     */
    @Override
    public MiniCardWithdrawalOrder selectByOrderNo(String orderNo) {
        return baseMapper.selectOne(new QueryWrapper<MiniCardWithdrawalOrder>().eq(MiniCardWithdrawalOrder.ORDER_NO, orderNo).last("limit 1"));
    }

    /**
     * 检验账户类型
     *
     * @param loginUser
     */
    private void checkAccountType(AccountInfo loginUser) {
        ArrayList<Integer> types = Lists.newArrayList(AccountType.Administrator, AccountType.MinVipCardMerchant, AccountType.MinVipCardMerchant);
        Arguments.isFalse(types.contains(loginUser.getType()), "您无权访问");
    }
}
